package com.ruoyi.finance.service.impl;

import com.ruoyi.IndexDtoByThree;
import com.ruoyi.activiti.api.RemoteActivitiService;
import com.ruoyi.caigou.api.RemoteBuyBackOrderService;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.finance.dto.IndexReceiveOrderDto;
import com.ruoyi.finance.mapper.*;
import com.ruoyi.finance.service.IReciveOrderService;
import com.ruoyi.store.api.RemoteStockOutService;
import com.ruoyi.system.api.constants.BuyBackOrderConstants;
import com.ruoyi.system.api.domain.caigou.BuyBackOrder;
import com.ruoyi.system.api.domain.finance.*;
import com.ruoyi.system.api.domain.store.StockOut;
import com.ruoyi.system.api.dto.ActApprovalDTO;
import com.ruoyi.xiaoshou.api.RemoteSaleBackService;
import com.ruoyi.xiaoshou.api.RemoteSaleOrderService;
import com.ruoyi.xiaoshou.domain.SaleOrder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 财务收款单Service业务层处理
 *
 * @author wl
 * @date 2024-11-02
 */
@Service
@Slf4j
public class ReciveOrderServiceImpl implements IReciveOrderService {
    @Autowired
    private ReciveOrderMapper reciveOrderMapper;

    @Autowired
    private ReciveOrderDetailMapper reciveOrderDetailMapper;

    @Autowired
    private PayTypeMapper payTypeMapper;

    @Autowired
    private RemoteActivitiService remoteActivitiService;

    @Autowired
    private ReciveReqMapper reciveReqMapper;

    @Autowired
    private RemoteSaleOrderService remoteSaleOrderService;

    @Autowired
    private RemoteBuyBackOrderService remoteBuyBackOrderService;

    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private RemoteStockOutService remoteStockOutService;

    @Autowired
    private RemoteSaleBackService remoteSaleBackService;

    /**
     * 查询财务收款单
     *
     * @param id 财务收款单主键
     * @return 财务收款单
     */
    public ReciveOrder selectReciveOrderById(Integer id) {
        ReciveOrder reciveOrder = reciveOrderMapper.selectReciveOrderById(id);
        List<ReciveOrderDetail> reciveOrderDetailList = reciveOrderDetailMapper.selectReciveOrderDetailListByOrderId(reciveOrder.getId());
        reciveOrder.setReciveOrderDetailList(reciveOrderDetailList);
        log.info("ReciveOrderServiceImpl selectReciveOrderById reciveOrder:{}", reciveOrder);
        return reciveOrder;
    }

    @Override
    public IndexReceiveOrderDto getSaleOrderReciveCountAndMoney() {
        return reciveOrderMapper.getSaleOrderReciveCountAndMoney();
    }

    @Override
    public IndexDtoByThree getReceiveOrderThreeCountToIndex() {
        return reciveOrderMapper.getReceiveOrderThreeCountToIndex();
    }

    @Override
    public IndexReceiveOrderDto getBuyBackReciveOrderCountAndMoney() {
        return reciveOrderMapper.getBuyBackReciveOrderCountAndMoney();
    }

    /**
     * 查询财务收款单列表
     *
     * @param reciveOrder 财务收款单
     * @return 财务收款单
     */
    public List<ReciveOrder> selectReciveOrderList(ReciveOrder reciveOrder) {
        return reciveOrderMapper.selectReciveOrderList(reciveOrder);
    }

    /**
     * 新增财务收款单
     *
     * @param reciveOrder 财务收款单
     * @return 结果
     */
    @Transactional
    public AjaxResult insertReciveOrder(ReciveOrder reciveOrder) {
        //校验单据编号
        AjaxResult ajaxResult = checkOrderCode(reciveOrder.getOrderCode());
        Integer checkCode = (Integer) ajaxResult.get("code");
        if (checkCode != 200) {
            return ajaxResult;
        }
        //校验单据类型
        if (reciveOrder.getPaymentType() == null) {
            return AjaxResult.error("单据类型不能为空");
        }
        //校验单据日期
        if (reciveOrder.getOrderDate() == null) {
            return AjaxResult.error("单据日期不能为空");
        }
        //根据单据类型校验客户或供应商是否为空
        if (reciveOrder.getPaymentType() == 2 && reciveOrder.getCustomerId() == null) {
            return AjaxResult.error("客户名称不能为空");
        }
        if (reciveOrder.getPaymentType() == 3 && reciveOrder.getSupplierId() == null) {
            return AjaxResult.error("供应商名称不能为空");
        }

        reciveOrder.setMoney(BigDecimal.ZERO);
        //校验收款单明细是否为空
        List<ReciveOrderDetail> reciveOrderDetailList = reciveOrder.getReciveOrderDetailList();
        if (reciveOrderDetailList == null || reciveOrderDetailList.isEmpty()) {
            return AjaxResult.error("收款单明细不能为空");
        }

        //计算总金额
        for (ReciveOrderDetail reciveOrderDetail : reciveOrderDetailList) {
            //校验金额
            if (reciveOrderDetail.getMoney() == null) {
                return AjaxResult.error("明细金额不能为空");
            }
            //校验金额是否为正数
            if (BigDecimal.ZERO.compareTo(reciveOrderDetail.getMoney()) > 0) {
                return AjaxResult.error("明细金额必须大于0");
            }

            //计算总金额
            reciveOrder.setMoney(reciveOrder.getMoney().add(reciveOrderDetail.getMoney()));
        }


        //创建人信息
        reciveOrder.setCreateBy(SecurityUtils.getUsername());
        reciveOrder.setCreateDate(new Date());
        //赋值单据状态为已提交
        reciveOrder.setOrderStatus(BuyBackOrderConstants.ORDER_STATUS_SUBMITTED);
        //已核销金额赋值为0
        reciveOrder.setVerMoney(BigDecimal.ZERO);
        //状态初始化，未生效、未关闭、未作废、未删除
        reciveOrder.setIsEffect(0);
        reciveOrder.setIsClose(0);
        reciveOrder.setIsCancel(0);
        reciveOrder.setIsDel(0);

        //持久化到数据库
        int addNum = reciveOrderMapper.insertReciveOrder(reciveOrder);
        if (addNum <= 0) {
            return AjaxResult.error("新增失败");
        }

        //收款单明细
        for (ReciveOrderDetail reciveOrderDetail : reciveOrderDetailList) {

            //赋值创建人信息
            reciveOrderDetail.setCreateBy(SecurityUtils.getUsername());
            reciveOrderDetail.setCreateDate(new Date());
            reciveOrderDetail.setIsDel(0);

            //赋值财务收款单id
            reciveOrderDetail.setReciveOrderId(reciveOrder.getId());

            //持久化到数据库
            addNum = reciveOrderDetailMapper.insertReciveOrderDetail(reciveOrderDetail);
            if (addNum <= 0) {
                throw new RuntimeException("新增失败");
            }
        }

        //添加收款单activiti流程
        ActApprovalDTO actApprovalDTO = new ActApprovalDTO();
        actApprovalDTO.setProcessDefinitionKey("reciveOrderBPMN");
        actApprovalDTO.setOrderCode(reciveOrder.getOrderCode());
        String taskName = "";
        if (reciveOrder.getPaymentType() == 1) {
            taskName = "销售预收单";
        } else if (reciveOrder.getPaymentType() == 2) {
            taskName = "销售收款单";
        } else if (reciveOrder.getPaymentType() == 3) {
            taskName = "采购退货收款单";
        }
        actApprovalDTO.setTaskName(reciveOrder.getOrderCode() + taskName);
        //财务经理部门id
        actApprovalDTO.setDeptId(103);
        AjaxResult addApprovalAjaxResult = remoteActivitiService.addApproval(actApprovalDTO);
        Integer code = (Integer) addApprovalAjaxResult.get("code");
        if (code != 200) {
            throw new RuntimeException("新增失败");
        }
        return AjaxResult.success();
    }

    /**
     * 修改财务收款单
     *
     * @param reciveOrder 财务收款单
     * @return 结果
     */
    @Override
    public AjaxResult updateReciveOrder(ReciveOrder reciveOrder) {
        //校验单据id是否为空
        if (reciveOrder.getId() == null) {
            return AjaxResult.error("单据id不能为空");
        }

        //校验收款单明细是否为空
        List<ReciveOrderDetail> reciveOrderDetailList = reciveOrder.getReciveOrderDetailList();
        if (reciveOrderDetailList == null || reciveOrderDetailList.isEmpty()) {
            return AjaxResult.error("收款单明细不能为空");
        }

        //计算总金额
        for (ReciveOrderDetail reciveOrderDetail : reciveOrderDetailList) {
            //校验金额
            if (reciveOrderDetail.getMoney() == null) {
                return AjaxResult.error("明细金额不能为空");
            }
            //校验金额是否为正数
            if (BigDecimal.ZERO.compareTo(reciveOrderDetail.getMoney()) > 0) {
                return AjaxResult.error("明细金额必须大于0");
            }

            //计算总金额
            reciveOrder.setMoney(reciveOrder.getMoney().add(reciveOrderDetail.getMoney()));
        }

        //修改人信息
        reciveOrder.setModifyBy(SecurityUtils.getUsername());
        reciveOrder.setModifyDate(new Date());


        //持久化到数据库
        int updNum = reciveOrderMapper.updateReciveOrder(reciveOrder);
        if (updNum <= 0) {
            return AjaxResult.error("新增失败");
        }

        //删除原先的收款单明细
        updNum = reciveOrderDetailMapper.deleteReciveOrderDetailByReciveOrderId(reciveOrder.getId());
        if (updNum <= 0) {
            throw new RuntimeException("修改删除明细失败");
        }

        //收款单明细
        for (ReciveOrderDetail reciveOrderDetail : reciveOrderDetailList) {
            //赋值创建人信息
            reciveOrderDetail.setCreateBy(SecurityUtils.getUsername());
            reciveOrderDetail.setCreateDate(new Date());
            reciveOrderDetail.setIsDel(0);

            //赋值财务收款单id
            reciveOrderDetail.setReciveOrderId(reciveOrder.getId());

            //持久化到数据库
            updNum = reciveOrderDetailMapper.insertReciveOrderDetail(reciveOrderDetail);
            if (updNum <= 0) {
                throw new RuntimeException("修改添加明细失败");
            }
        }

        return AjaxResult.success();
    }

    /**
     * 批量删除财务收款单
     *
     * @param ids 需要删除的财务收款单主键
     * @return 结果
     */
    @Override
    public AjaxResult deleteReciveOrderByIds(Integer[] ids) {
        int delNum = reciveOrderMapper.deleteReciveOrderByIds(ids);
        log.info("ReciveOrderServiceImpl deleteReciveOrderByIds delNum:{}", delNum);
        if (delNum < ids.length) {
            return AjaxResult.error("删除失败");
        }
        return AjaxResult.success();
    }

    /**
     * 删除财务收款单信息
     *
     * @param id 财务收款单主键
     * @return 结果
     */
    @Override
    public AjaxResult deleteReciveOrderById(Integer id) {
        int delNum = reciveOrderMapper.deleteReciveOrderById(id);
        log.info("ReciveOrderServiceImpl deleteReciveOrderById delNum:{}", delNum);
        if (delNum <= 0) {
            return AjaxResult.error("删除失败");
        }
        return AjaxResult.success();
    }

    /**
     * @return com.ruoyi.common.core.web.domain.AjaxResult
     * @description 校验单据编号
     * @date 2024/11/2 上午10:41
     * @Param code:
     **/
    public AjaxResult checkOrderCode(String orderCode) {

        //校验单据编号
        if (StringUtils.isBlank(orderCode)) {
            return AjaxResult.error("单据编号不能为空");
        }
        int count = reciveOrderMapper.selectReciveOrderCountByOrderCode(orderCode);
        log.info("checkOrderCode count:{}", count);
        if (count > 0) {
            return AjaxResult.error("单据编号已存在");
        }
        return AjaxResult.success();

    }

    /**
     * @return com.ruoyi.common.core.web.domain.AjaxResult
     * @description 获取所有支付方式列表
     * @date 2024/11/11 下午3:34
     **/
    public AjaxResult getPayTypeList() {
        List<PayType> payTypeList = payTypeMapper.selectPayTypeList();
        log.info("getPayTypeList payTypeList:{}", payTypeList);
        return AjaxResult.success(payTypeList);
    }

    /**
     * @return com.ruoyi.system.api.domain.finance.ReciveOrder
     * @description 根据财务收款单编号获取财务收款单
     * @date 2024/11/11 下午4:57
     * @Param orderCode:
     **/
    public ReciveOrder selectReciveOrderByOrderCode(String orderCode) {
        ReciveOrder reciveOrder = reciveOrderMapper.selectReciveOrderByOrderCode(orderCode);
        List<ReciveOrderDetail> reciveOrderDetailList = reciveOrderDetailMapper.selectReciveOrderDetailListByOrderId(reciveOrder.getId());
        reciveOrder.setReciveOrderDetailList(reciveOrderDetailList);
        log.info("selectReciveOrderByOrderCode reciveOrder:{}", reciveOrder);
        return reciveOrder;
    }

    /**
     * @return com.ruoyi.common.core.web.domain.AjaxResult
     * @description 根据收款单编号修改，sql语句修改已核销金额
     * @date 2024/11/19 上午9:26
     * @Param reciveOrder:
     **/
    public AjaxResult updateReciveOrderByOrderCodeOfVerMoney(ReciveOrder reciveOrder) {
        int updNum = reciveOrderMapper.updateReciveOrderByOrderCodeOfVerMoney(reciveOrder);
        log.info("ReciveOrderServiceImpl updateReciveOrderByOrderCodeOfVerMoney updNum:{}", updNum);
        return AjaxResult.success();
    }

    /**
     * @return com.ruoyi.common.core.web.domain.AjaxResult
     * @description 根据财务收款单编号审核财务收款单
     * @date 2024/11/11 下午5:03
     * @Param reciveOrder:
     **/
    @Transactional
    public AjaxResult auditReciveOrderByOrderCode(ReciveOrder reciveOrder) {
        //修改单据阶段为已审核：3
        reciveOrder.setOrderStatus(BuyBackOrderConstants.ORDER_STATUS_APPROVED);
        //设置审核人
        reciveOrder.setApprovalId(Math.toIntExact(SecurityUtils.getUserId()));
        //如果审核通过设置生效时间,生效状态为已生效
        if (reciveOrder.getApprovalResult() == BuyBackOrderConstants.APPROVAL_APPROVED) {
            reciveOrder.setEffectDate(new Date());
            reciveOrder.setIsEffect(1);
        } else if (reciveOrder.getApprovalResult() == BuyBackOrderConstants.APPROVAL_REJECTED) {
            //如果审核未通过设置为关闭
            reciveOrder.setIsClose(1);
        }

        //设置修改人 修改时间+修改人名称
        reciveOrder.setModifyBy(SecurityUtils.getUsername());
        reciveOrder.setModifyDate(new Date());

        int updNum = reciveOrderMapper.updateReciveOrderByOrderCode(reciveOrder);
        log.info("ReciveOrderServiceImpl auditReciveOrderByOrderCode updNum:{}", updNum);
        if (updNum <= 0) {
            return AjaxResult.error("审核失败");
        }
        //如果审核不通过则返回
        if (reciveOrder.getApprovalResult() != BuyBackOrderConstants.APPROVAL_APPROVED) {
            return AjaxResult.success();
        }

        //获取财务收款单详情
        reciveOrder = reciveOrderMapper.selectReciveOrderByOrderCode(reciveOrder.getOrderCode());
        //如果是销售预收单不自动核销
        if (reciveOrder.getPaymentType() == 1) {
            return AjaxResult.success();
        }
        List<ReciveOrderDetail> reciveOrderDetailList = reciveOrderDetailMapper.selectReciveOrderDetailListByOrderId(reciveOrder.getId());
        reciveOrder.setReciveOrderDetailList(reciveOrderDetailList);


        //销售退货逻辑
        /*通过付款详情获取原单号对应的退货订单，改变退货订单的已付金额，如果付款大于已付金额，
         * */
//        if(reciveOrder.getPaymentType()==8){
//            for (ReciveOrderDetail reciveOrderDetail: reciveOrderDetailList) {
//                String code = reciveOrderDetail.getSrcOrderCode();
//                R<SaleBack> result = remoteSaleBackService.getSaleBackByCode(code);
//                SaleBack saleBack = result.getData();
//                if (saleBack.getTotal()==null){
//                    log.error("remoteSaleBackService.getSaleBackByCode fail");
//                    throw new RuntimeException("获取退货订单失败");
//                }
//                BigDecimal payNow = reciveOrderDetail.getMoney();
//                BigDecimal payMoney = saleBack.getPayMoney();
//                BigDecimal realMoney = saleBack.getRealMoney();
//                BigDecimal needPay = realMoney.subtract(payMoney);
//                if(payNow.compareTo(needPay)>0){
//
//                }
//            }
//        }

        //用变量接收收款单已核销金额
        BigDecimal verMoney = BigDecimal.ZERO;
        for (ReciveOrderDetail reciveOrderDetail : reciveOrderDetailList) {
            if (reciveOrderDetail.getAccountId() != null) {
                //修改账户金额
                //获取账户
                Account account = accountMapper.selectAccountById(Long.valueOf(reciveOrderDetail.getAccountId()));
                account.setMoney(account.getMoney().add(reciveOrderDetail.getMoney()));
                account.setUpdateBy(SecurityUtils.getUsername());
                account.setUpdateDate(new Date());
                updNum = accountMapper.updateAccount(account);
                log.info("ReciveOrderServiceImpl auditReciveOrderByOrderCode updAccount updNum:{}", updNum);
            }

            //金额校验，多余的金额留存后续核销 设置财务收款单的核销金额
            //修改销售应收单 修改采购退货应收单
            //源单号绑定应收单
            String srcOrderCode = reciveOrderDetail.getSrcOrderCode();
            //根据源单号获取财务应收单
            ReciveReq reciveReq = reciveReqMapper.selectReciveReqByOrderCode(srcOrderCode);
            //获取未结算金额
            BigDecimal unSettleMoney = reciveReq.getMoney().subtract(reciveReq.getVerMoney());
            //收款详情核销金额
            BigDecimal detailVerMoney = BigDecimal.ZERO;
            //如果收款单金额大于等于未结算金额则将销售应收单的实收赋值为应收
            if (reciveOrderDetail.getMoney().compareTo(unSettleMoney) >= 0) {
                verMoney = verMoney.add(unSettleMoney);
                detailVerMoney = unSettleMoney;
                //应收单单据阶段设置为执行完：4 已核销金额设置为应收金额 应收单关闭
                reciveReq.setVerMoney(reciveReq.getMoney());
                reciveReq.setOrderStatus(4);
                reciveReq.setIsClose(1);
            }
            //如果收款单金额小于未结算金额则将销售应收单的实收赋值为收款单金额+原单已核销金额
            if (reciveOrderDetail.getMoney().compareTo(unSettleMoney) < 0) {
                detailVerMoney = reciveOrderDetail.getMoney();
                verMoney = verMoney.add(reciveOrderDetail.getMoney());
                //应收单已核销金额设置为收款单金额+原单已核销金额
                reciveReq.setVerMoney(reciveReq.getVerMoney().add(reciveOrderDetail.getMoney()));
            }
            //修改财务应收单
            reciveReq.setModifyBy(SecurityUtils.getUsername());
            reciveReq.setModifyDate(new Date());
            //校验应收与实收是否相等 相等则关闭财务应收单 单据阶段修改为执行完：4
            if (reciveReq.getVerMoney().compareTo(reciveReq.getMoney()) >= 0) {
                reciveReq.setIsClose(1);
                reciveReq.setOrderStatus(BuyBackOrderConstants.ORDER_STATUS_EXECUTED);
            }
            updNum = reciveReqMapper.updateReciveReq(reciveReq);
            log.info("ReciveOrderServiceImpl auditReciveOrderByOrderCode updateReciveReq updNum:{}", updNum);

            //如果财务收款单类型为销售收款 通过则修改销售应收单 销售订单
            //根据应收单源单号获取出库单
            String reciveReqSrcOrderCode = reciveReq.getSrcOrderCode();
            StockOut stockOut = remoteStockOutService.getInfoByStockOutCode(reciveReqSrcOrderCode).getData();
            if (reciveOrder.getPaymentType() == 2) {
                //修改销售订单
                SaleOrder saleOrder = remoteSaleOrderService.getOrderByCode(stockOut.getOrderCode());
                if (saleOrder.getPayStatus() == 0) {
                    //如果原实收为0则修改收款状态为部分收款
                    saleOrder.setPayStatus(1);
                }
                //设置实际收款 将原先收款加上详情核销金额
                saleOrder.setPayMoney(saleOrder.getPayMoney().add(detailVerMoney));
                //校验实收与总金额是否相等 相等则修改收款状态为已收款
                if (saleOrder.getPayMoney().compareTo(saleOrder.getTotal()) >= 0) {
                    saleOrder.setPayStatus(2);
                    //如果销售订单收款状态为已收款 订单状态执行完：3
                    saleOrder.setOrderStatus(3);
                }
                saleOrder.setOutStockNumber(0);
                //调用修改销售订单方法修改状态
                updNum = remoteSaleOrderService.edit(saleOrder, SecurityConstants.INNER);
                log.info("ReciveOrderServiceImpl auditReciveOrderByOrderCode editSaleOrder updNum:{}", updNum);
            } else if (reciveOrder.getPaymentType() == 3) {
                //修改采购退货单
                R<BuyBackOrder> buyBackOrderR = remoteBuyBackOrderService.getInfoByBuyBackOrderCode(stockOut.getOrderCode());
                BuyBackOrder buyBackOrder = buyBackOrderR.getData();
                if (buyBackOrder.getPayStatus() == BuyBackOrderConstants.PAY_STATUS_WAIT) {
                    //如果原实收为0则修改收款状态为部分收款:2
                    buyBackOrder.setPayStatus(BuyBackOrderConstants.PAY_STATUS_MIDDLE);
                }
                //设置实际收款 将原先收款加上详情核销金额
                buyBackOrder.setRealInPrice(buyBackOrder.getRealInPrice().add(detailVerMoney));
                //校验实收与总金额是否相等 相等则修改收款状态为全部收款:3
                if (buyBackOrder.getRealInPrice().compareTo(buyBackOrder.getAllInPrice()) >= 0) {
                    buyBackOrder.setPayStatus(BuyBackOrderConstants.PAY_STATUS_END);
                    //如果采购退货单收款状态为全部收款 出库状态为全部出库则设置为执行完 关闭采购退货单
                    if (buyBackOrder.getStockStatus() == BuyBackOrderConstants.STOCK_STATUS_END) {
                        buyBackOrder.setOrderStatus(BuyBackOrderConstants.ORDER_STATUS_EXECUTED);
                        buyBackOrder.setIsClose(1);
                    }
                }
                // TODO 审核通过后自动生成应收核销单
                AjaxResult ajaxResult = remoteBuyBackOrderService.editAfterAuditReciveOrder(buyBackOrder);
                log.info("ReciveOrderServiceImpl auditReciveOrderByOrderCode editBuyBackOrder updNum:{}", ajaxResult);
            }
        }

        //判断收款单已核销金额
        reciveOrder.setVerMoney(verMoney);
        //校验核销金额与金额是否相等
        if (reciveOrder.getVerMoney().compareTo(reciveOrder.getMoney()) == 0) {
            reciveOrder.setOrderStatus(BuyBackOrderConstants.ORDER_STATUS_EXECUTED);
            reciveOrder.setIsClose(1);
        }
        updNum = reciveOrderMapper.updateReciveOrder(reciveOrder);
        log.info("ReciveOrderServiceImpl auditReciveOrderByOrderCode setVerMoney updNum:{}", updNum);
        return AjaxResult.success();
    }

}
